package game.server;

import game.Game;
import game.log.Logger;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

import shared.io.game.EndGame;
import shared.io.game.Player;
import shared.io.messages.ErrorMessage;
import shared.io.messages.ServerMessage;
import shared.io.startup.Waiting;

public final class Server extends Thread {
   
   public static final int PORT = 4444;
   private ServerSocket serverSocket;
   private Socket userSocket;
   private List<ClientSession> clientSessions;
   private ObjectManager objectManager;
   private Game game;
   
   /**
    * @param refresh
    * refresh rate in milliseconds
    * how long each move from room to room takes
    */
   public Server(Game game) {
      this.game = game;
      objectManager = new ObjectManager(this, game);
      try {
         serverSocket = new ServerSocket(PORT);
      } catch (IOException e) {
         Logger.write("Setting up a ServerSocket on port " + PORT + " failed.");
      }
      clientSessions = new ArrayList<ClientSession>();
      start();
   }

   @Override
   public void run() {
      try {
         while(true) {
            listenConnections();
         }
      } catch (IOException e) {
         Logger.write("Listening to connections failed. " + e.getMessage());
      }
   }
   
   /**
    * Listens to incoming connections
    */
   private void listenConnections() throws IOException {
      userSocket = serverSocket.accept();
      ClientSession clientSession = new ClientSession(userSocket, this, game);
      if (clientSessionSize() >= game.getMaxPlayers()) {
         clientSession.sendObject(new ErrorMessage("Game is full."));
         //clientSession.close();
      } else {
         if (clientSessionSize() < game.getMaxPlayers() - 1) {
            
            
         }
         addClientSession(clientSession);
         clientSession.start();
         clientSession.sendObject(new Waiting());
         clientSession.sendObject(new ServerMessage("WAITING"));
      }
   }
   
   private synchronized void addClientSession(ClientSession session) {
      clientSessions.add(session);
   }
   
   public synchronized void removeClientSession(ClientSession session) {
      clientSessions.remove(session);
   }
   
   public synchronized int clientSessionSize() {
      return clientSessions.size();
   }
   
   public synchronized List<ClientSession> getClientSessions() {
      return clientSessions;
   }
   
   public void manageObject(Object object, ClientSession session) {
      objectManager.manageObject(object, session);
   }
   
   public synchronized void sendObjectToSessions(Object object) {
      for (ClientSession session : getClientSessions()) {
         session.sendObject(object);
      }
   }
   
   public synchronized void sendObjectToSessions(Object object, ClientSession sender) {
      sender.sendObject(object);
      for (ClientSession session : getClientSessions()) {
         if (session != sender) {
            session.sendObject(object);
         }
      }
   }   
}